package gae.testjig.data;

import gae.testjig.dao.DaoContact;
import gae.testjig.dao.DaoDuplicateException;
import gae.testjig.dao.DaoException;
import gae.testjig.dao.DaoNotFoundException;
import gae.testjig.dao.DaoOrganization;
import gae.testjig.dto.Contact;
import gae.testjig.dto.ContactGroup;
import gae.testjig.dto.Organization;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.jdo.PersistenceManager;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class BizLogicContacts {

//	final static private Logger logger = Logger.getLogger(BizLogicContacts.class.getSimpleName());
	
	private Key orgKey;
	
	public BizLogicContacts(Key orgKey) {
		this.orgKey = orgKey;
	}
	
	public ContactGroup createContactGroup(String name) throws DaoException {
		PersistenceManager pm = PMF.getForTransactions().getPersistenceManager();
		try {
			pm.currentTransaction().begin();
			Organization org = DaoOrganization.findByOrganizationKey(pm, this.orgKey);
			LinkedList<ContactGroup> groups = org.getContactGroups();
			if ( groups != null ) {
				for ( ContactGroup cg : groups ) {
					if ( name.equals(cg.getName()) ) {
						throw new DaoDuplicateException("Contact Group "+name+" already exists.");
					}
				}
			} else {
				groups = new LinkedList<ContactGroup>();
				org.setContactGroups(groups);
			}
			ContactGroup cg = new ContactGroup();
			cg.setName(name);
			groups.add(cg);
			pm.makePersistent(org);
			ContactGroup answer = pm.detachCopy(cg);
			pm.currentTransaction().commit();
			return answer;
		}
		finally {
			if (pm.currentTransaction().isActive()) {
		        pm.currentTransaction().rollback();
		    }
			pm.close();
		}
	}

	public List<Contact> getContactsByGroup(String groupKeyString) throws DaoException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Organization org = DaoOrganization.findByOrganizationKey(pm, orgKey);
		List<ContactGroup> groups = org.getContactGroups();
		Key groupKey = KeyFactory.stringToKey(groupKeyString);
		Key key = null;
		if ( groups != null ) {
			for ( ContactGroup cg : groups ) {
				if ( groupKey.equals(cg.getContactGroupKey()) ) {
					key = cg.getContactGroupKey();
					break;
				}
			}
		}
		if ( key == null ) {
			throw new DaoNotFoundException("group not found.");
		}
		
		List<Contact> answer = new ArrayList<Contact>();
		List<Contact> contacts = DaoContact.findByContactGroup(pm, key);
		if ( contacts != null ) {
			answer = (List<Contact>) pm.detachCopyAll(contacts);
		}
		pm.close();
		return answer;
	}
	
	public ArrayList<Contact> getAllContacts() throws DaoException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		ArrayList<Contact> answer = new ArrayList<Contact>();
		List<Contact> contacts = DaoContact.findByOrganization(pm, orgKey);
		if ( contacts != null ) {
			answer = new ArrayList<Contact>((List<Contact>) pm.detachCopyAll(contacts));
		}
		pm.close();
		return answer;
	}

	public Contact createRandomContact(String groupKeyString) throws DaoException {
		Contact c = RandomContact.createRandomContact();
		return createContact(c, groupKeyString);
	}

	public Contact createContact(Contact c, String groupKeyString) throws DaoException {
		PersistenceManager pm = PMF.getForTransactions().getPersistenceManager();
		try {
			pm.currentTransaction().begin();
			Organization org = DaoOrganization.findByOrganizationKey(pm, orgKey);
			List<ContactGroup> groups = org.getContactGroups();
			Key key = null;
			if ( null != groupKeyString ) { // may be no group for this new contact
				Key groupKey = KeyFactory.stringToKey(groupKeyString);
				if ( groups != null ) {
					for ( ContactGroup cg : groups ) {
						if ( groupKey.equals(cg.getContactGroupKey()) ) {
							key = cg.getContactGroupKey();
						}
					}
				}
				if ( key == null ) {
					throw new DaoNotFoundException("group not found.");
				}
			}
			Contact c2 = pm.detachCopy( DaoContact.create(pm, org.getOrganizationKey(), c.getName(), c.getPhoneNumber(), key) );
			pm.currentTransaction().commit();
			return c2;
		}
		finally {
			if (pm.currentTransaction().isActive()) {
		        pm.currentTransaction().rollback();
		    }
			pm.close();
		}
	}

	public void updateGroupMembership(ArrayList<Key> contactKeys, String groupKeyString, boolean isAdded) throws DaoException {
		Key groupKey = KeyFactory.stringToKey(groupKeyString);
		PersistenceManager pm = PMF.getForTransactions().getPersistenceManager();
		try {
			pm.currentTransaction().begin();
			Organization org = DaoOrganization.findByOrganizationKey(pm, orgKey);
			if ( org == null ) {
				throw new DaoNotFoundException("no such organization.");
			}
			List<ContactGroup> groups = org.getContactGroups();
			boolean found = false;
			for ( ContactGroup cg : groups ) {
				if ( cg.getContactGroupKey().equals(groupKey) ) {
					found = true;
					break;
				}
			}
			if ( ! found ) {
				throw new DaoNotFoundException("no such group found.");
			}

			for ( Key contactKey : contactKeys ) {
				Contact c = DaoContact.findByContactKey(pm, contactKey);
				// first look for existing group
				int index = c.getContactGroups().indexOf(groupKey);
				if ( isAdded && (index<0) ) {
					c.getContactGroups().add(groupKey);
				} else if ( !isAdded && (index>-1) ) {
					c.getContactGroups().remove(index);
				}
				pm.makePersistent(c);
			}

			pm.currentTransaction().commit();
		}
		finally {
			if (pm.currentTransaction().isActive()) {
		        pm.currentTransaction().rollback();
		    }
			pm.close();
		}
	}

	public void deleteGroup(String groupKeyString) throws DaoException {
		Key contactGroupKey = KeyFactory.stringToKey(groupKeyString);
		PersistenceManager pm = PMF.getForTransactions().getPersistenceManager();
		try {
			pm.currentTransaction().begin();
			Organization org = DaoOrganization.findByOrganizationKey(pm, orgKey);
			if ( org == null ) {
				throw new DaoNotFoundException("no such organization.");
			}
			List<Contact> contacts = DaoContact.findByContactGroup(pm, contactGroupKey);
			for ( Contact c : contacts ) {
//logger.info("nuke group "+contactGroupKey+" from "+c.getName());
				c.getContactGroups().remove(contactGroupKey);
				pm.makePersistent(c);
			}
			LinkedList<ContactGroup> groups = org.getContactGroups();
			for (int i=0;i<groups.size();i++) {
				if ( groups.get(i).getContactGroupKey().equals(contactGroupKey) ) {
					groups.remove(i);
					pm.makePersistent(org);
					break;
				}
			}
			pm.currentTransaction().commit();
		}
		finally {
			if (pm.currentTransaction().isActive()) {
		        pm.currentTransaction().rollback();
		    }
			pm.close();
		}
	}

	public void deleteContacts(ArrayList<Key> contactKeys) throws DaoException {
		PersistenceManager pm = PMF.getForTransactions().getPersistenceManager();
		try {
			pm.currentTransaction().begin();
			Organization org = DaoOrganization.findByOrganizationKey(pm, orgKey);
			if ( org == null ) {
				throw new DaoNotFoundException("no such organization.");
			}
			for ( Key contactKey : contactKeys ) {
				Contact c = DaoContact.findByContactKey(pm, contactKey);
				pm.deletePersistent(c);
			}
			pm.currentTransaction().commit();
		}
		finally {
			if (pm.currentTransaction().isActive()) {
		        pm.currentTransaction().rollback();
		    }
			pm.close();
		}
	}

}
